package com.ruicar.afs.cloud.basic.common.controller;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.basic.common.condition.ContractStatusCondition;
import com.ruicar.afs.cloud.basic.common.entity.*;
import com.ruicar.afs.cloud.basic.common.service.*;
import com.ruicar.afs.cloud.basic.common.utils.MqSendUtils;
import com.ruicar.afs.cloud.basic.common.vo.ContractBasicInfoVO;
import com.ruicar.afs.cloud.basic.proceeds.debit.entity.BasicDebitBatchDetails;
import com.ruicar.afs.cloud.basic.proceeds.debit.service.BasicDebitBatchDetailsService;
import com.ruicar.afs.cloud.batch.entity.AfsBatchInfo;
import com.ruicar.afs.cloud.batch.service.AfsBatchInfoService;
import com.ruicar.afs.cloud.bizcommon.voucher.service.VoucherFlowService;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.core.util.SpringContextHolder;
import com.ruicar.afs.cloud.common.modules.constant.VoucherBuriedPointNo;
import com.ruicar.afs.cloud.common.modules.contract.enums.ContractBusinessEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.ContractStatusEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.PersonRoleTypeEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.RepaymentStatusEnum;
import com.ruicar.afs.cloud.common.modules.dto.mq.loan.contractdto.LoanActivateReceiveNoticeDTO;
import com.ruicar.afs.cloud.common.modules.dto.mq.voucher.VoucherFlowInfoDto;
import com.ruicar.afs.cloud.common.modules.enums.BusinessType;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.manage.api.dto.BasicMainInfoDto;
import com.ruicar.afs.cloud.manage.api.dto.BasicPrintTemplateInfoDto;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author: Lee
 * @date: 2020/5/11 19:39
 * @description: 合同基本信息controller
 */
@Slf4j
@RestController
@RequestMapping("/contractInfo")
@AllArgsConstructor
public class ContractBasicInfoController {
    private final MqSendUtils mqSendUtils;
    private final VoucherFlowService voucherFlowService;
    private final AfsBatchInfoService afsBatchInfoService;
    private final BasicMainInfoService basicMainInfoService;
    private final BasicDebitInfoService basicDebitInfoService;
    private final BasicCarDetailsService basicCarDetailsService;
    private final BasicChannelInfoService basicChannelInfoService;
    private final BasicCustBaseInfoService basicCustBaseInfoService;
    private final BasicRepaymentPlanService basicRepaymentPlanService;
    private final BasicAffiliatedUnitService basicAffiliatedUnitService;
    private final BasicDebitBatchDetailsService debitBatchDetailsService;
    private final BasicCustContactDetailsService basicCustContactDetailsService;
    private final BasicAssetsRepaymentPlanService basicAssetsRepaymentPlanService;
    private final BasicContractCustRelationService basicContractCustRelationService;

    @ApiOperation(value = "根据合同号码查询合同信息")
    @PostMapping("/findByContractNo")
    public IResponse findByContractNo(@RequestParam("contractNo") String contractNo) {
        BasicMainInfo basicMainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>lambdaQuery().eq(BasicMainInfo::getContractNo, contractNo));

        BasicContractCustRelation basicContractCustRelation = basicContractCustRelationService.getOne(Wrappers.<BasicContractCustRelation>lambdaQuery()
                .eq(BasicContractCustRelation::getContractNo, contractNo)
                .eq(BasicContractCustRelation::getCustRole, PersonRoleTypeEnum.MAIN_PERSON));

        if (basicContractCustRelation == null) {
            return new IResponse().fail("没有查询到客户信息");
        }

        BasicCustBaseInfo basicCustBaseInfo = basicCustBaseInfoService.getOne(Wrappers.<BasicCustBaseInfo>lambdaQuery()
                .eq(BasicCustBaseInfo::getCustNo, basicContractCustRelation.getCustNo()));
        if (basicCustBaseInfo == null) {
            return new IResponse().fail("没有查询到客户信息");
        }

        List<BasicCustContactDetails> basicCustContactDetails = basicCustContactDetailsService.list(Wrappers.<BasicCustContactDetails>lambdaQuery().eq(BasicCustContactDetails::getCustNo, basicCustBaseInfo.getCustNo()));
        BasicChannelInfo basicChannelInfo = basicChannelInfoService.getOne(Wrappers.<BasicChannelInfo>lambdaQuery()
                        .eq(BasicChannelInfo::getContractNo, contractNo)
                , false
        );
        BasicDebitInfo basicDebitInfo = basicDebitInfoService.getOne(Wrappers.<BasicDebitInfo>lambdaQuery().eq(BasicDebitInfo::getContractNo, contractNo));
        List<BasicRepaymentPlan> repaidTermNo = basicRepaymentPlanService.list(Wrappers.<BasicRepaymentPlan>lambdaQuery()
                .eq(BasicRepaymentPlan::getContractNo, contractNo)
                .eq(BasicRepaymentPlan::getStatus, RepaymentStatusEnum.REPAID)
                .orderByAsc(BasicRepaymentPlan::getTermNo));

        Date dt = null;
        if (EmptyUtils.isNotEmpty(repaidTermNo)) {
            dt = repaidTermNo.get(repaidTermNo.size() - 1).getActualPaymentDate();
        }

        ContractBasicInfoVO vo = new ContractBasicInfoVO();
        vo.setBasicChannelInfo(basicChannelInfo != null ? basicChannelInfo : new BasicChannelInfo());
        vo.setBasicCustBaseInfo(basicCustBaseInfo != null ? basicCustBaseInfo : new BasicCustBaseInfo());
        vo.setBasicCustContactDetails(EmptyUtils.isNotEmpty(basicCustContactDetails) ? basicCustContactDetails : new ArrayList<>());
        vo.setBasicDebitInfo(basicDebitInfo != null ? basicDebitInfo : new BasicDebitInfo());
        vo.setBasicMainInfo(basicMainInfo != null ? basicMainInfo : new BasicMainInfo());
        vo.setActualPaymentDate(dt);
        return new IResponse().setData(vo);
    }

    @ApiOperation(value = "更新合同状态")
    @PostMapping("/updateContractStatus")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<Boolean> updateContractStatus(@RequestBody ContractStatusCondition contractStatus) {
        basicMainInfoService.update(Wrappers.<BasicMainInfo>lambdaUpdate()
                .eq(BasicMainInfo::getContractNo, contractStatus.getContractNo())
                .set(BasicMainInfo::getContractStatus, contractStatus.getContractStatus()));
        debitBatchDetailsService.update(Wrappers.<BasicDebitBatchDetails>lambdaUpdate()
                .eq(BasicDebitBatchDetails::getContractNo, contractStatus.getContractNo())
                .set(BasicDebitBatchDetails::getContractStatus, contractStatus.getContractStatus()));
        basicAssetsRepaymentPlanService.update(Wrappers.<BasicAssetsRepaymentPlan>lambdaUpdate()
                .eq(BasicAssetsRepaymentPlan::getContractNo, contractStatus.getContractNo())
                .set(BasicAssetsRepaymentPlan::getStatus, RepaymentStatusEnum.CANCEL_CONTRACT));
        BasicMainInfo basicMainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>lambdaUpdate()
                .eq(BasicMainInfo::getContractNo, contractStatus.getContractNo()));
        basicMainInfo.setContractStatus(contractStatus.getContractStatus());
        //通过mq向进件发送合同取消数据
        mqSendUtils.sendApply(basicMainInfo);
        //通过mq向案件发送合同取消状态
        LoanActivateReceiveNoticeDTO dto = LoanActivateReceiveNoticeDTO.builder()
                .contractNo(basicMainInfo.getContractNo())
                .caseDate(DateUtil.date())
                .caseType(ContractBusinessEnum.cancelContract)
                .contractEndDate(basicMainInfo.getEndDate())
                .build();
        mqSendUtils.contractStatusChange(dto);
        //凭证数据流水数据
        VoucherFlowInfoDto voucherFlowInfoDto = new VoucherFlowInfoDto();
        voucherFlowInfoDto.setTransNo(basicMainInfo.getContractNo());
        voucherFlowInfoDto.setContractNo(basicMainInfo.getContractNo());
        voucherFlowInfoDto.setBuriedPointNo(VoucherBuriedPointNo.contractLoanCancel);// 埋点编号
        voucherFlowInfoDto.setDealerName(basicMainInfo.getChannelFullName());
        voucherFlowInfoDto.setTransNo(basicMainInfo.getContractNo());
        voucherFlowInfoDto.setKeepAccountDate(new Date());
        voucherFlowInfoDto.setBusinessType((BusinessType) AfsEnumUtil
                .getEnum(AfsEnumUtil.key(basicMainInfo.getBusinessType()), BusinessType.class));
        voucherFlowService.sendFlow(voucherFlowInfoDto);
        return new IResponse().setData(true);
    }

    @ApiOperation(value = "根据合同号码查询合同信息")
    @PostMapping("/mainInfofindByContractNo")
    public IResponse mainInfofindByContractNo(@RequestParam("contractNo") String contractNo) {
        BasicMainInfo basicMainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>lambdaQuery().eq(BasicMainInfo::getContractNo, contractNo));
        Assert.isTrue(basicMainInfo != null, MessageFormat.format("合同编号：{0}，合同信息不存在！", contractNo));
        BasicMainInfoDto dto = new BasicMainInfoDto();
        dto.setBusinessType(basicMainInfo.getBusinessType());
        dto.setChannelName(basicMainInfo.getChannelFullName());
        dto.setProductName(basicMainInfo.getProductName());
        dto.setContractNo(basicMainInfo.getContractNo());
        dto.setId(basicMainInfo.getId());
        return new IResponse().setData(dto);
    }

    @ApiOperation(value = "根据合同号码查询车辆信息")
    @PostMapping("/basicPrintTemplateInfo")
    public IResponse basicPrintTemplateInfo(@RequestParam("contractNo") String contractNo, @RequestParam("carId") Long carId) {
        BasicContractCustRelation contractCustRelation = basicContractCustRelationService.getOne(Wrappers.<BasicContractCustRelation>lambdaQuery()
                .eq(BasicContractCustRelation::getContractNo, contractNo)
                .eq(BasicContractCustRelation::getCustRole, AfsEnumUtil.key(PersonRoleTypeEnum.MAIN_PERSON)));
        BasicCustBaseInfo basicCustBaseInfo = basicCustBaseInfoService.getOne(Wrappers.<BasicCustBaseInfo>lambdaQuery()
                .eq(BasicCustBaseInfo::getCustNo, contractCustRelation.getCustNo()));
        BasicAffiliatedUnit basicAffiliatedUnit = basicAffiliatedUnitService.getOne(Wrappers.<BasicAffiliatedUnit>lambdaQuery()
                .eq(BasicAffiliatedUnit::getContractNo, contractNo));
        BasicCarDetails basicCarDetails = basicCarDetailsService.getById(carId);
        BasicPrintTemplateInfoDto dto = new BasicPrintTemplateInfoDto();
        dto.setCertNo(contractCustRelation != null ? basicCustBaseInfo.getCertNo() : null);
        dto.setCarVin(basicCarDetails != null ? basicCarDetails.getCarVin() : null);
        dto.setEngineNo(basicCarDetails != null ? basicCarDetails.getEngineNo() : null);
        dto.setAffiliatedName(basicAffiliatedUnit != null ? basicAffiliatedUnit.getAffiliatedName() : null);
        dto.setSocUniCrtCode(basicAffiliatedUnit != null ? basicAffiliatedUnit.getSocUniCrtCode() : null);
        return new IResponse().setData(dto);
    }


    @Transactional(rollbackFor = Exception.class)
    public IResponse closeContract(String contractNo, AfsBatchInfo afsBatchInfo) {
        //step2： 获取当前日结日期
        if (afsBatchInfo == null || StringUtils.isEmpty(afsBatchInfo.getBatchDate())) {
            throw new AfsBaseException("获取日结日期失败，不能执行合同关闭，请先处理完切日异常后再执行合同关闭");
        }
        DateTime batchDate = DateUtil.parse(afsBatchInfo.getBatchDate());
        basicMainInfoService.update(Wrappers.<BasicMainInfo>lambdaUpdate().eq(BasicMainInfo::getContractNo, contractNo)
                .set(BasicMainInfo::getCloseDate, batchDate));
        BasicMainInfo basicMainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>lambdaUpdate().eq(BasicMainInfo::getContractNo, contractNo));
        //通过mq向进件发送合同取消数据
        mqSendUtils.sendApply(basicMainInfo);
        //通过mq向案件发送合同取消状态
        LoanActivateReceiveNoticeDTO dto = LoanActivateReceiveNoticeDTO.builder()
                .contractNo(basicMainInfo.getContractNo())
                .caseDate(DateUtil.date())
                .caseType(ContractBusinessEnum.cancelContract)
                .contractEndDate(basicMainInfo.getEndDate())
                .build();
        mqSendUtils.contractStatusChange(dto);
        return new IResponse().setData(afsBatchInfo.getBatchDate());
    }

    @ApiOperation(value = "更新合同关闭状态")
    @PostMapping("/closeContract")
    public IResponse processMessage(@RequestParam("contractNo") String contractNo) {
        AfsBatchInfo afsBatchInfo = afsBatchInfoService.getSystemBatchInfo("icos");
        return SpringContextHolder.getBean(ContractBasicInfoController.class).closeContract(contractNo, afsBatchInfo);
    }

    @ApiOperation(value = "判断合同是否已关闭或者取消")
    @PostMapping("/cancelOrClose")
    public IResponse cancelOrClose(@RequestParam("contractNo") String contractNo) {
        String status;
        BasicMainInfo contract = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>lambdaQuery().eq(BasicMainInfo::getContractNo, contractNo));
        if (contract.getContractStatus().equals(ContractStatusEnum.contractCancel)) {
            status = "contractCancel";
        } else if (contract.getCloseDate() != null) {
            status = "contractClose";
        } else {
            status = "other";
        }
        return new IResponse().setData(status);
    }

    @ApiOperation(value = "获取合同当前状态")
    @PostMapping("/getContractStatusByContractNo")
    public IResponse<ContractStatusEnum> getContractStatusByContractNo(@RequestParam("contractNo") String contractNo) {
        BasicMainInfo contract = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda().eq(BasicMainInfo::getContractNo, contractNo));
        IResponse response = new IResponse().setData(contract.getContractStatus());
        return response;
    }
}
